#IF REGISTERED
DOBAT:
        MOV AX,ROOM
        CMP AX,[BAT]
        IF NE JMP BAT_MOVE
        MOV ES,AX,VIDSEG_MAIN
        MOV CX,3
        MOV BX,BAT_STR1
        MOV DI,[BAT+2]
        MOV AX,DI
        DIV v_160
        MOV DH,AH
     B1:
        CMP B[BX],020
        IF NE MOV B[ES:DI],020
        CMP DH,158
        JAE >L1
        CMP B[BX+1],020
        IF NE MOV B[ES:DI+2],020
        CMP DH,156
        JAE >L1
        CMP B[BX+2],020
        IF NE MOV B[ES:DI+4],020
        CMP DH,154
        JAE >L1
        CMP B[BX+3],020
        IF NE MOV B[ES:DI+6],020
     L1:
        ADD DI,160
        ADD BX,4
        CMP DI,160*24
        JAE >B2
        LOOP B1
     B2:
;  Check for player touch
;        CMP JUSTWON?,0
;        IF NE JMP LONG >B8
;        CMP CARRYING,BAT
;        IF E JMP LONG >B8
;        MOV AX,[BAT+2]
;        DIV v_160
;        MOV DX,AX
;        MOV AX,PL_AD
;        DIV v_160
;        SUB AL,DL
;        CMP AL,2
;        JA BAT_MOVE
;        SUB AH,DH
;        CMP AH,-2
;        JL BAT_MOVE
;        CMP AH,6
;        JA BAT_MOVE
;        MOV CARRYING,BAT
;        MOV SI,BAT
;        CALL PICKUP_BUMPOBJ
;        SUB AX,PL_AD
;        MOV BX,BAT_CARRYING
;        CMP BX,SWALLOWED
;        JNE >L2
;        MOV AX,BAT_CD
;        ADD AX,322
;        TEST B[BX+3],080
;        IF NZ ADD AX,160
;        NEG AX
;     L2:MOV CARRY_DISTANCE,AX
;        MOV SOUND_PTR,SOUND_PICKUP
;        MOV SOUND_START,-1
BAT_MOVE:
;        CMP HALFCNT,0
;        IF NZ JMP LONG >B8
        CMP JUSTWON?,0
        IF NE JMP LONG >B8
        CMP CARRYING,BAT
        IF E JMP LONG >B8
        MOV BX,[BAT]
        CMP BX,ROOM
        JNE >L3                      ; If bat is here,
        CMP BX,[OBJECT+OSZ*13]       ; and whistle is here,
        JNE >L3
        CMP CARRYING,OBJECT+OSZ*13   ; and player is carrying whistle,
        IF E JMP LONG >B8            ; then bat is frozen and can't move.
     L3:CALL GETMAPADDR
        MOV DX,[BAT+4]
        CMP DX,0                      ; no movement at all?
        IF E MOV [BAT+4],DX,0101      ; YES!  Can't have that.
        CMP DL,0  ;horiz movement?
        JE >B6     ;no
        MOV AX,[BAT+2]
        DIV v_160
        CMP DL,0  ;left?
        JG >B4
        CMP AH,4
        JAE >B3
        MOV BX,[BX]      ;  new room
        MOV [BAT],BX
        CALL GETMAPADDR
        ADD W[BAT+2],160
     B3:
        SUB W[BAT+2],4
        JMP >B6
     B4:
        CMP AH,156
        JB >B5
        MOV BX,[BX+2]    ;   new room
        MOV [BAT],BX
        CALL GETMAPADDR
        SUB W[BAT+2],160
     B5:
        ADD W[BAT+2],4
     B6:
        CMP DH,0
        JGE >B7   ;not up
        SUB W[BAT+2],160
        JNS >B8
        ADD W[BAT+2],160*24
        MOV AX,[BX+4]   ; new room
        MOV [BAT],AX
        JMP >B8
     B7:
        JE >B8    ;not down
        ADD W[BAT+2],160
        CMP W[BAT+2],160*24
        JB >B8
        SUB W[BAT+2],160*24
        MOV AX,[BAT]
        CALL GETROOMBELOW
;        MOV AX,[BX+6]   ;  new room
;        XCHG [BAT],AX
;        MOV ES,CS
;        MOV DI,CASTLE_1STRM
;        MOV CX,5
;        REPNE SCASW
;        JNE >B8
;        SUB DI,CASTLE_1STRM+2
;        SHR DI,1
;        CMP GATE[DI],0  ;castle open?
;        JNE >L1         ;yes
;        SHL DI,1
;        MOV AX,CASTLE_LOCKEDIN[DI]    ;no
        MOV [BAT],AX
;        JMP >B8
        JNZ >B8
     L1:MOV W[BAT+2],(15*160)+76
     B8:
        MOV AX,ROOM
        CMP AX,[BAT]
        IF NE JMP LONG >B12
        MOV ES,AX,VIDSEG_MAIN
        MOV DL,0
        MOV CX,3
        MOV BX,BAT_STR1
        MOV DI,[BAT+2]
        TEST LCNT,4
        IF NZ MOV BX,BAT_STR2
        ADD BX,VGA
        CALL CHECKBLINK
        IF NZ JMP LONG >B12
        MOV AX,DI
        DIV v_160
        MOV DH,AH
    B11:
        MOV AH,[ES:DI+1]
        AND AH,0F0
        MOV SI,DI
        CMP ROOMCOLOR,CAT
        JNE >P1
        CALL CHECKWALL_SI
        JNZ >P2
     P1:
        MOV AL,[BX]
        CMP AL,020
        IF NE MOV [ES:DI],AX
     P2:
        CMP DH,158
        JAE >L1
        MOV AH,[ES:DI+3]
        AND AH,0F0
        CMP ROOMCOLOR,CAT
        JNE >P1
        ADD SI,2
        CALL CHECKWALL_SI
        JNZ >P2
     P1:
        MOV AL,[BX+1]
        CMP AL,020
        IF NE MOV [ES:DI+2],AX
     P2:
        CMP DH,156
        JAE >L1
        MOV AH,[ES:DI+5]
        AND AH,0F0
        CMP ROOMCOLOR,CAT
        JNE >P1
        ADD SI,2
        CALL CHECKWALL_SI
        JNZ >P2
     P1:
        MOV AL,[BX+2]
        CMP AL,020
        IF NE MOV [ES:DI+4],AX
     P2:
        CMP DH,154
        JAE >L1
        MOV AH,[ES:DI+7]
        AND AH,0F0
        CMP ROOMCOLOR,CAT
        JNE >P1
        ADD SI,2
        CALL CHECKWALL_SI
        JNZ >L1
     P1:
        MOV AL,[BX+3]
        CMP AL,020
        IF NE MOV [ES:DI+6],AX
     L1:
        ADD DI,160
        ADD BX,4
        CMP DI,160*24
        JAE >B12
        LOOP >J0
        JMP >B12
     J0:JMP B11
    B12:
;  Check for: Bat Takes a New Interest (new object/dragon in sights?)
        CMP JUSTWON?,0
        IF NE JMP DONE_BAT
        MOV AX,[BAT]
        MOV DI,BAT_PRIORITY
    B13:
        MOV BL,[DI]
        MOV BH,0
        LEA SI,[OBJECT][BX]
        CMP BAT_CARRYING,SI
        JE >B14  ;skip
        CMP AX,[SI]
        JNE >B14   ;this object not in bat's room
        MOV BAT_OBJINSIGHTS,SI
        JMP >B19
    B14:
        INC DI
        CMP B[DI],-1
        JNE B13
    B15:
        MOV SI,DRAGON+DRSZ*3
    B16:
        CMP AX,[SI]
        JNE >B17
        CMP BAT_CARRYING,SI
        JE >B17
        MOV BAT_OBJINSIGHTS,SI
        JMP >B19
    B17:
        SUB SI,DRSZ
        CMP SI,DRAGON
        JAE B16
; decrement Hold-counter, and alter movement as appropriate
    B19:
        SUB BAT_HOLDCNT,1
        JC >B20
     J1:JMP DONE_BAT
    B20:
        INC BAT_HOLDCNT
        MOV BX,BAT_OBJINSIGHTS
        CMP BX,BAT_CARRYING
        JE J1   ;must not chase after what he's already got
        MOV AX,[BAT]
        CMP AX,[BX]   ;bat in same room as target object?
        IF NE JMP BATSEARCH
        MOV AX,[BX+2]
        AND AH,07F
        DIV v_160
        MOV DX,AX
        MOV AX,[BAT+2]
        DIV v_160
        CMP AH,DH   ;bat left of object/dragon?
        JNB >B21    ;no
        MOV B[BAT+4],1
        JMP >B22
    B21:
        MOV B[BAT+4],-1
        IF E INC B[BAT+4]   ;make zero, if neither right nor left
    B22:
        CMP AL,DL   ;bat above object/dragon?
        JNB >B23
        MOV B[BAT+5],1
        JMP >B24
    B23:
        JE >B24     ;if neither above nor below
        MOV B[BAT+5],-1
    B24:
;check for bat's contact with object
        SUB DH,AH
        CMP DH,6
        JA >J0
        SUB DL,AL
        JG >J0
        CMP DL,-1
        JL >J0
        CMP CARRYING,BX        ;If player was carrying it...
        IF E MOV CARRYING,-1   ;then not anymore
;
        PUSH BX
        MOV BX,BAT_CARRYING
        CMP BX,SWALLOWED
        JNE >L1
        PUSH BX
        CALL SWCARBYBAT_ERASE
        POP BX
        MOV AX,[BX+2]
        ADD AX,322
        CMP AX,160*24
        JB >L0
        PUSH AX
        PUSH BX
        MOV BX,[BX]
        CALL GETMAPADDR
        MOV AX,[BX+6]
        MOV ROOM,AX
        MOV LASTGOOD_RM,AX
        POP BX
        POP AX
        SUB AX,160*24
     L0:MOV PL_AD,AX
        MOV LASTGOOD_AD,AX
     L1:
        POP BX
;
        MOV BAT_CARRYING,BX
        MOV BAT_CD,168
        CMP DL,0
        IF NE SUB BAT_CD,160*2
        CMP DH,0
        IF E SUB BAT_CD,2
        MOV BAT_HOLDCNT,216
;        MOV SI,BX
;        CALL ERASE_OBJ
     J0:JMP DONE_BAT
  BATSEARCH:
        PUSH BX
        MOV BX,AX
        CALL GETMAPADDR
        MOV DI,BX
        POP BX
        MOV AX,[BX]
        MOV ES,CS
        SCASW     ;target object/dragon in room on left?
        JNE >B25
        MOV W[BAT+4],0FF  ;directly left
        JMP >B28
    B25:
        SCASW    ;target in room on right?
        JNE >B26
        MOV W[BAT+4],1  ;directly right
        JMP >B28
    B26:
        SCASW   ;target in room above?
        JNE >B27
        MOV W[BAT+4],0FF00  ;directly up
        JMP >B28
    B27:
        SCASW   ;target in room below?
        JNE >B28
        MOV W[BAT+4],0100   ;directly down
    B28:
#ENDIF
DONE_BAT:
;
        CALL CHECKBLINK
        IF Z CALL PUTGATE
        TEST LC_FLAG,0C0
        JZ >L1
        MOV SI,LINE_MARGIN
        TEST LC_FLAG,040
        IF NZ MOV SI,158-LINE_MARGIN
         CALL PUTLINE
     L1:
        CMP JUSTWON?,0
        JE >J1
#IF REGISTERED
        CMP JUSTWON?,MAX_JUSTWON?+1
        IF A CALL SECRETMESSAGE
#ENDIF
        JMP DOSOUND
     J1:
        TEST LC_FLAG,020
        JNZ >Q1
     Q0:JMP NOKEYINGATE
     Q1:
        MOV AL,COPEN_CNT
        OR AL,CCLOSE_CNT
        JNZ Q0
        MOV ES,DS
        MOV DI,CASTLE_TABLE
        MOV CX,5
        MOV AX,ROOM
        REPNE SCASW
        MOV AL,4
        SUB AL,CL
        MOV AH,OSZ
        MUL AH
        MOV SI,OBJECT+OSZ
        ADD SI,AX
        MOV AX,ROOM
        CMP AX,[SI]
        JNE Q0
        MOV AX,(160*17)+82
        TEST LC_FLAG,010   ;gate open?
        IF NZ SUB AX,3*160
        CMP LOC,AX
        JAE NOKEYINGATE
        CMP LOC,(160*14)+70
        JB NOKEYINGATE
        MOV AX,LOC
        DIV v_160
        CMP AH,70
        JB NOKEYINGATE
        CMP AH,82
        JA NOKEYINGATE
        TEST LC_FLAG,010
        JNZ >L2
        MOV COPEN_CNT,6
        OR LC_FLAG,010
        MOV DL,-1
SETGATESTATUS:
        MOV ES,DS
        MOV DI,CASTLE_TABLE
        MOV CX,5
        MOV AX,ROOM
        REPNE SCASW
        MOV BX,4
        SUB BX,CX
        MOV GATE[BX],DL
        JMP SHORT NOKEYINGATE
     L2:
        MOV CCLOSE_CNT,6
        AND LC_FLAG,0EF
        MOV DL,0
        JMP SETGATESTATUS
NOKEYINGATE:
        TEST LCNT,1
        JZ DOSOUND
        CMP COPEN_CNT,0
        JE >L3
     A1:DEC COPEN_CNT
        JZ A1
        JMP DOSOUND
     L3:
        CMP CCLOSE_CNT,0
        JE DOSOUND
        DEC CCLOSE_CNT
;        JNZ DOSOUND
;        AND LC_FLAG,0EF
;        MOV ES,DS
;        MOV DI,CASTLE_TABLE
;        MOV CX,5
;        MOV AX,ROOM
;        REPNE SCASW
;        MOV BX,4
;        SUB BX,CX
;        MOV GATE[BX],0
DOSOUND:
        CALL SOUND
;
        CMP SHOWDIF_CNT,0
        JLE >L1
        DEC SHOWDIF_CNT
        JNZ >L1
        MOV ES,AX,VIDSEG_MAIN
        MOV DI,0F00
        MOV CX,80
        MOV AX,0720
        REP STOSW
        CMP ROOMCOLOR,CAT
        JNE >L1
        MOV DI,03F00
        MOV CX,80
        REP STOSW
     L1:
;
;
;
;
        CALL UPDATE
        CALL LOOPWAIT
        CALL JOYSTICK_CALIBRATE
        CALL GETTIME
        MOV LOOP_TIMER,AX
        CALL HIDECHANGES
;
        WWMOV PL_AD,LASTGOOD_AD
        MOV AX,LASTGOOD_RM
        XCHG AX,ROOM
        CMP AX,ROOM
        IF NE CALL PUTROOM
;
        CMP B CTRL_BRK_PRESSED?,0
        IF NE JMP EXIT_PROGRAM
        MOV BX,0FF
     G1:MOV AH,1
        INT 016     ; AH = scan code, AL = ASCII char
        JZ >G2      ; no more keys, exit loop
        MOV AH,0
        INT 016     ; actually read in key
        MOV BX,AX
        JMP SHORT G1
     G2:
        CMP MOVEMODE,v_StickyKeys
        JNE >S1
        CMP B KP5,0
        IF NE JMP PLAYER_HALT
     S1:
        MOV AX,BX
        CMP BX,0FF
        IF E JMP MOVE
        CMP AH,sc_S
        JNE >S2
        XOR SOUND?,0FF
        IF Z CALL SOUND_OFF
        MOV AL,0
        CALL PRINTDIFS
        JMP MOVE
     S2:
        CMP AH,sc_ESC
        IF E JMP ESC_PRESSED  ;LONG >M2
        CMP AL,3
        IF E JMP EXIT_PROGRAM
        CMP PROG_JUST_STARTED?,0
        JNE >G3
        CMP AH,sc_F4
        JNE >G3
        CMP JUSTWON?,0
        IF NE JMP SELECTGAME
        JMP RESET
     G3:
        CMP AH,sc_F9
        JNE >K2
        INC SHOWDIF_CNT
        JZ >K1
        MOV SHOWDIF_CNT,-1
        JMP >A3
     K1:INC SHOWDIF_CNT
        JMP MOVE
     K2:
        CMP AH,sc_F10
        JE >A3
        CMP AH,sc_F5
        JNE >A2
        NOT LDIF
        JMP >A3
     A2:CMP AH,sc_F6
        JNE >A4
        NOT RDIF
     A3:MOV AL,0
        CALL PRINTDIFS
        JMP MOVE
     A4:
        CMP AH,sc_F1
        JNE >A5
        CALL SHOWHELP
        JMP MOVE
     A5:
        CMP AH,sc_F7
        JNE >A6
        INC MOVEMODE
        CMP MOVEMODE,4
        IF AE MOV MOVEMODE,0
        MOV AL,0
        CALL PRINTDIFS
        JMP MOVE
     A6:
#IF REGISTERED
        CMP AH,sc_Shift_F1
        JNE >A7
        CALL LOADGAME
        JMP MOVE
     A7:
        CMP AH,sc_Shift_F2
        JNE >A8
        CMP PROG_JUST_STARTED?,0
        JNE >A8
        CMP JUSTWON?,0
        JNE >A8
        CMP ROOM,0
        JE >A8
        CALL SAVEGAME
        JMP MOVE
     A8:
        CMP AH,sc_A
        JNE >Z1
        CMP ROOM,21
        JNE >Z1
        PUSH AX
        MOV AH,2
        INT 016
        AND AL,0F
        CMP AL,0C
        JBE >Z1         ; Shift, Ctrl & Alt must be down
        MOV SHIFTCTRLALTA,SHOWDIF_CNT_length * 2
        MOV SOUND_PTR,SOUND_NYAHH
        MOV SOUND_START,-1
     Z1:
#ENDIF
        CMP AH,sc_F2
        JNE >A9
        MOV AH,0F
        INT 010     ; get current text page in BH
        XOR COLOR?,0FF
        JZ >C2
;        CALL WAITFORBLANK
        CMP VGA,0
        JE >C0
        MOV AX,01010
        MOV BX,6
        MOV DH,BROWNDAC
        MOV CX,[(OFFSET BROWNDAC)+1]
        INT 010        ; restore Brown
        CALL PUTROOM
        JMP MOVE
     C0:
        MOV AX,083
        INT 010         ;restore color the CGA way
     C1:
        MOV AH,5
        MOV AL,BH
        INT 010      ; restore text page following text mode reset
        CALL DISABLEBLINK
        HIDE_CURSOR MAIN_TXTPG
        HIDE_CURSOR ALLGRAY_TXTPG
        JMP MOVE
     C2:
;        CALL WAITFORBLANK
        CMP VGA,0
        JNE >C3
        MOV AX,82       ;black-and-white text mode
        INT 010
        JMP C1
     C3:
        MOV AX,01015
        MOV BX,6
        INT 010
        MOV BROWNDAC,DH
        MOV W [(OFFSET BROWNDAC)+1],CX   ; save Brown
        MOV AX,01010
        MOV BX,6
NEWCOL: MOV CX,0808
        MOV DH,CH
        INT 010        ; change Brown to dark gray
        CALL PUTROOM
        JMP MOVE
     A9:
        CMP AH,sc_F3
        IF NE JMP CHECK_FOR_BUTTON
        MOV ES,AX,VIDSEG
        MOV DI,160*24+74
        MOV CX,8
        MOV AX,0720
        REP STOSW
        MOV JUSTWON?,0
#IF REGISTERED
        CMP ROOM,0
        JNE >A50
        INC GAMENO
        CMP GAMENO,6
        IF AE MOV GAMENO,1
    A50:
#ENDIF
        JMP SELECTGAME
ESC_PRESSED:
;     M2:
;        CMP AH,sc_ESC
;        JNE PLAYER_HALT
        MOV AH,2
        INT 016
        TEST AL,4       ; Ctrl pressed?
        IF Z JMP PLAYER_HALT  ; no
EXIT_PROGRAM:
        MOV ES,AX,0B800
        XOR DI,DI
        MOV CX,80*25
        MOV AX,0720
        REP STOSW       ; clear screen
        MOV CURSORROWONEXIT,0
EXIT_NOCLS:
RESTOREINT MACRO
        PUSH DS
        MOV AX,025 BY 0#1
        LDS DX,CS:AD_INT#1
        CLI
        INT 021   ;reset INT vector to original address
        STI
        POP DS
#EM
        CLI
        MOV AL,036         ;
        OUT 043,AL         ;
        XOR AL,AL
        OUT 040,AL         ;
        NOP
        OUT 040,AL         ;
        STI
        RESTOREINT 0
   CMP BIOSJOYSTICK,0
   IF E RESTOREINT 8
        RESTOREINT 9
        RESTOREINT 1B
        RESTOREINT 24
        CALL SOUND_OFF
        MOV AX,01202
        MOV BL,030
        INT 010    ; restore 16-scanline-per-char text (VGA only)
        MOV AX,083
        INT 010
        MOV AH,2
        XOR BH,BH
        MOV DH,CURSORROWONEXIT
        XOR DL,DL
        INT 010   ; place cursor
        MOV AX,04C00
        INT 021
PLAYER_HALT:
        DMOV JOYVALS,START_JOYVALS
        JMP SHORT MOVE
CHECK_FOR_BUTTON:
        MOV BUTTONS,0FF
     L1:
        CMP AH,sc_B
        JE >B1
        CMP AH,sc_Space
        JE >B1
        CMP AH,sc_Insert
        JNE >L2
     B1:
        MOV BUTTONS,0
        JMP SHORT MOVE
     L2:
        PUSH AX
        MOV AL,AH
        CALL ALinG_Q?
        POP AX
        JNE PLAYER_HALT  ;M2
        MOV AL,AH
        CALL CONV_KEY
    MOVE:
        CMP MOVEMODE,v_Joystick
        JNE >J0
        CALL JOYSTICK
     J0:
        CMP MOVEMODE,v_AtariJoy
        JNE >J1
        CALL ATARIJOYSTICK
     J1:
        CMP MOVEMODE,v_KeyInt
        JNE >J2
        CALL CONV_KEY_INT
        CALL CONV_KEY
     J2:
        CMP PROG_JUST_STARTED?,0
        IF NE JMP MAIN
        CMP JUSTWON?,0
        IF NE DMOV JOYVALS,START_JOYVALS
        MOV BX,BAT_CARRYING
        CMP BX,0
        JE >Q1
        CMP BX,SWALLOWED
        JE >Q2
     Q1:JMP LONG >A0
     Q2:PUSH BX
        CALL SWCARBYBAT_ERASE
        POP BX
        MOV CX,[BX]
        MOV AX,[BX+2]
        ADD AX,322
        CMP AX,160*24
        JB >S1
        SUB AX,160*24
        PUSH AX
        PUSH BX
        MOV BX,CX
        CALL GETMAPADDR
        MOV CX,[BX+6]
        JMP >S2
     S1:
        PUSH AX
        DIV v_160
        CMP AH,0  ;pushed into next room (room on right)?
        POP AX
        JNE >S3
        SUB AX,160
        PUSH AX
        PUSH BX
        MOV BX,CX
        CALL GETMAPADDR
        MOV CX,[BX+2]
     S2:POP BX
        POP AX
     S3:
        MOV PL_AD,AX
        MOV LASTGOOD_AD,AX
        MOV LASTGOOD_RM,CX
        XCHG ROOM,CX
        CMP CX,ROOM
        IF NE CALL PUTROOM
        MOV W[OFFSET SWCARBYBAT_BG],0
        CALL CHECKACTUAL
        IF A DEC SWCARBYBAT_BG    ; if NZ and NC
        ADD PL_AD,2
        CALL CHECKACTUAL
        IF A DEC SWCARBYBAT_BG[1]
        SUB PL_AD,2
        JMP ENTERCASTLE
        JMP >A2
     A0:
        MOV AH,CAT
        CMP ROOMCOLOR,AH
        JNE >A1
        MOV AH,0C0
     A1:
        CALL CHECKWALL
        JZ >L1
        JC >L1
        MOV AH,ROOMCOLOR
        CMP AH,-1
        JNE >L1
        PUSH BX
        LDFLASHCOLOR AH
        SHL AH,1
        SHL AH,1
        SHL AH,1
        SHL AH,1
        POP BX
     L1:
        CMP JUSTWON?,0
        JNE >A2
        MOV ES,CX,VIDSEG_MAIN   ; Erase player
        MOV DI,LASTGOOD_AD
        MOV AL,[ES:DI+1]
        AND AL,0F
        OR AL,AH
        MOV [ES:DI+1],AL
        MOV AL,[ES:DI+3]
        AND AL,0F
        OR AL,AH
        MOV [ES:DI+3],AL
;
     A2:
        MOV BX,ROOM
        CALL GETMAPADDR
        WWMOV TEMP_RM,LASTGOOD_RM
        WWMOV TEMP_AD,LASTGOOD_AD
        MOV TOUCHED_OBJ,-1
;        MOV TMP_HBLOCKED_BY_OBJ?,0
;
        MOV AX,LASTGOOD_AD
        DIV v_160
        PUSH AX
        MOV AX,JLEFT
        CMP HMOV,AX   ;leftward?
        POP AX
        JA >M5
        SUB PL_AD,4
        CMP AH,0
        JNE >M3
        MOV AX,[BX]
        CMP ROOM,15     ; } where only player can go
        IF E MOV AX,21  ; }
        ADD PL_AD,160
        CALL NEWROOM
     M3:
;        CALL MOVCO
;        CALL BLOCKED_H
;        JZ GOOD_H
;        JMP >M4
        JMP >M6
  GOOD_H:
        WWMOV LASTGOOD_AD,PL_AD
        WWMOV LASTGOOD_RM,ROOM
     M4:JMP MOVEV
     M5:
        PUSH AX
        MOV AX,JRIGHT
        CMP HMOV,AX   ;rightward?
        POP AX
        JB M4
        ADD PL_AD,4
        CMP AH,156
        JB >M6
        MOV AX,[BX+2]
        CMP GAMENO,1
        JE >Q1
        CMP ROOM,4      ; } where only player can go
        IF E MOV AX,5   ; }
        CMP ROOM,18     ; }
        IF E MOV AX,21  ; }
     Q1:
        SUB PL_AD,160
        CALL NEWROOM
     M6:
        CALL MOVCO
        CALL BLOCKED_H
        JZ GOOD_H
;        IF C WWMOV TMP_HBLOCKED_BY_OBJ?,CARRYING
  MOVEV:
        MOV DX,160*24
        XOR AX,AX
        PUSH AX
        MOV AX,JUP
        CMP VMOV,AX   ;upward?
        POP AX
        JA >M9
        SUB PL_AD,0A0
        JS >L3
        JMP >M7
     L3:
        MOV AX,[BX+4]
        ADD PL_AD,DX
        CALL NEWROOM
     M7:
        MOV AX,-0A0
     M7A:
        PUSH AX,DX
        CALL MOVCO
        POP DX,AX
        CALL BLOCKED_V
        JZ GOOD_V
        JNC >M8
        WWMOV LASTGOOD_RM,TEMP_RM
        WWMOV LASTGOOD_AD,TEMP_AD
        JMP >M8
   GOOD_V:
        ADD LASTGOOD_AD,AX
        JNS >G1
        ADD LASTGOOD_AD,DX
        JMP >G2
     G1:
        CMP LASTGOOD_AD,DX
        JNAE M7B
        SUB LASTGOOD_AD,DX
     G2:
        WWMOV LASTGOOD_RM,ROOM
     M7B:
        CMP AX,0
        JE >M8
        CMP TOUCHED_OBJ,-1
        JE >M8
        WWMOV LASTGOOD_RM,TEMP_RM
        WWMOV LASTGOOD_AD,TEMP_AD
     M8:
;        CMP AX,0
;        JE >Y1
;        MOV AX,TOUCHED_OBJ  ;TMP_HBLOCKED_BY_OBJ?
;        CMP AX,-1
;        JE >Y1
;        CMP AX,CARRYING
;        JE >Y1
;        WWMOV LASTGOOD_AD,PL_AD
;        WWMOV LASTGOOD_RM,ROOM
;     Y1:
        JMP ENTERCASTLE
     M9:
        PUSH AX
        MOV AX,JDOWN
        CMP VMOV,AX   ;downward?
        POP AX
        JB M8
        ADD PL_AD,0A0
        CMP PL_AD,DX
        JNAE >M10
        MOV AX,ROOM          ;
        CALL GETROOMBELOW
        PUSHF
        SUB PL_AD,DX
        POPF
        JNE >L1              ; not leaving a castle
        PUSH AX
        MOV AX,(15*160)+80
        XCHG PL_AD,AX
        MOV LASTGOOD_AD,(14*160)+80
        DIV v_160
        CMP AH,80
        JAE >L0
        SUB PL_AD,4
        SUB LASTGOOD_AD,4
     L0:POP AX
        MOV LASTGOOD_RM,AX
     L1:
        CALL NEWROOM
    M10:
        MOV AX,0A0
        JMP M7A
NEWROOM:
        PUSH BX
        MOV BX,LASTGOOD_RM
        CMP BX,ROOM
        JE >L3
        MOV AX,BX
     L3:
        POP BX
        MOV ROOM,AX
        JMP PUTROOM
ENTERCASTLE:
        CMP ROOM,0
        JNE >L0
; first, check for "entering" Room 0
        CMP ENTERRM0_CNT,ENTERRM0_THRESHOLD
        JAE >L0               ; already "free"
        PUSH AX
        MOV AX,JRIGHT
        CMP HMOV,AX
        POP AX
        JB >R0
        PUSH AX
        MOV AX,JDOWN
        CMP VMOV,AX
        POP AX
        JB >R0
        INC ENTERRM0_CNT
        CMP ENTERRM0_CNT,ENTERRM0_THRESHOLD
        JB >L0
        ADD PL_AD,4
        ADD LASTGOOD_AD,4
        JMP >L0
     R0:
        MOV ENTERRM0_CNT,0
;
     L0:
;        TEST LC_FLAG,010  ; open castle?
;        JZ BUTTONCHECK
;        CMP PL_AD,(13*160)+74
;        JB BUTTONCHECK
;        CMP PL_AD,(14*160)+82
;        JA BUTTONCHECK
;        CMP PL_AD,(13*160)+82
;        JBE >L1
;        CMP PL_AD,(14*160)+74
;        JB BUTTONCHECK
        LEA SI,ROOM
        LEA BX,TEMP
        MOV W[BX],1 BY 2
        CALL OBJONOPENCASTLE?
        JNZ >L1
        LEA SI,LASTGOOD_RM
        CALL OBJONOPENCASTLE?
        JZ BUTTONCHECK
     L1:
        MOV ES,DS
        MOV DI,CASTLE_TABLE
        MOV CX,5
        MOV AX,ROOM
        REPNE SCASW
        MOV AX,[DI+10-2]
        MOV BX,4
        SUB BX,CX
        MOV GATE[BX],-1   ; force gate to be open
     L2:
        ADD PL_AD,160
        CMP PL_AD,23*160
        JB L2
        WWMOV LASTGOOD_AD,PL_AD
        CALL NEWROOM
        WWMOV LASTGOOD_RM,ROOM
BUTTONCHECK:
        CMP JUSTWON?,0
        JNE >L1
        TEST BUTTONS,010
        JNZ >L1
        MOV LASTKEY,'_'
        OR BUTTONS,010
        CMP CARRYING,-1
        JE >L1
        MOV AX,-1
        XCHG AX,CARRYING
        MOV STILLTOUCHING,AX
        MOV SOUND_PTR,SOUND_DROP
        MOV SOUND_START,-1
     L1:
        MOV AX,PL_AD
        CMP AX,LASTGOOD_AD
        IF E CALL MOVCO   ; if player hasn't moved
        JMP MAIN
MOVCO:
;  move carried object
        PUSH BX,SI
        CMP CARRYING,-1
        IF E JMP DONE_MOVEOBJ
        MOV SI,CARRYING
        CALL ERASE_OBJ
        MOV BX,ROOM
        MOV RM,BX
        CALL GETMAPADDR
        MOV DI,BX
        MOV AX,PL_AD
        ADD AX,CARRY_DISTANCE
        MOV LOC,AX
        JS >C4   ; off top edge?
;        DIV v_160
;        CMP AH,160   ; arbitrary number
;        JB >C2 ;1      ; off horizontal edge?
;        CMP AH,200
;        JA >C1        ; off left edge?
;                      ; no, so must be off right edge
;;
;        MOV AX,PL_AD  ; yes, assuming player is on right edge
;        DIV v_160     ;
;        CMP AH,80
;        JB >C1
        DIV v_160
        MOV DX,AX
        MOV AX,PL_AD
        DIV v_160
        CMP DH,40   ; if object is on left...
        JA >C1
        CMP AH,120  ; and player is on right...
        JB >C1
;                    ... then object's been pushed off right edge
        MOV BX,[DI+2]
        MOV [SI],BX
        CALL GETMAPADDR
        MOV DI,BX
        SUB LOC,160
;        PUSHF
;        CALL GETMAPADDR
;        MOV DI,BX
;        POPF
        JNS >C2
        JMP >C4   ;DONE_MOVEOBJ
     C1:
;        CALL SIZEOFOBJ  ;at [BX] and [BX+1]
;        MOV AX,PL_AD
;        DIV v_160
;        CMP AH,80      ; If player's horizontal < 80
;        JAE >C2        ;
;        MOV AX,LOC     ;
;        DIV v_160      ;
;        CMP AH,120     ; and object's is >120,
;        JBE >C2        ; then object is off left edge:
        CMP DH,120  ; if object is on right...
        JB >C2
        CMP AH,40   ; and player is on left...
        JA >C2
;   then object's been pushed off left side
        MOV BX,[DI]
        MOV [SI],BX
        ADD LOC,160
        CALL GETMAPADDR
        MOV DI,BX
;        JMP DONE_MOVEOBJ
     C2:
        CMP LOC,160*24    ; off bottom edge?
        JB DONE_MOVEOBJ
        CALL OBJ_OFFBOTTOM
        JMP SHORT DONE_MOVEOBJ
     C4:
        WWMOV RM,[DI+4]
        ADD LOC,160*24
DONE_MOVEOBJ:
        POP SI,BX
        RET
HIDECHANGES:
;  hide screen changes by copying screen to different
;  page and showing that page while changes are made
        PUSH DS
        MOV DS,AX,VIDSEG_MAIN
        MOV ES,AX,VIDSEG+0100*SCRATCH_TXTPG
        MOV SI,0
        MOV DI,0
        MOV CX,80*25
        REP MOVSW
        POP DS
        HIDE_CURSOR SCRATCH_TXTPG
        MOV AX,5 BY SCRATCH_TXTPG
        INT 010
; don't want to leave until we're in a vertical blank
;        CMP VGA,0
;        JE >H2
        MOV DX,03DA
     H1:
        IN AL,DX
        TEST AL,8
        JZ H1
     H2:
        RET
UPDATE:
;
; reveal changed screen
        MOV AX,5 BY MAIN_TXTPG
        CMP ROOMCOLOR,CAT
        JNE >R5
        CALL CHECKBLINK
        IF NZ MOV AX,5 BY ALLGRAY_TXTPG
     R5:
        INT 010
        RET
WAITFORBLANK:
        MOV DX,03DA
     W1:
        IN AL,DX
        TEST AL,8
        JZ W1           ;wait for current vertical blank to end
     W2:
        IN AL,DX
        TEST AL,8
        JZ W2           ;wait for next vertical blank
        RET
DISABLEBLINK:
        MOV AL,9                ;  16-color char backgrounds (CGA)
        MOV DX,03D8             ;
        OUT DX,AL               ;
        MOV AX,01003            ;  16-color char backgrounds (EGA/VGA)
        MOV BL,0                ;
        INT 010                 ;
        RET
